Skip to content

toolpath-gemini#21

Merged
benbaarber merged 1 commit intomainfrom
ben/gemini
Apr 20, 2026
Merged

toolpath-gemini#21
benbaarber merged 1 commit intomainfrom
ben/gemini

Conversation

@benbaarber
Copy link
Copy Markdown
Collaborator

Add toolpath-gemini — derive Toolpath documents from Gemini CLI conversations

Reads Gemini CLI conversation logs from ~/.gemini/tmp/<project>/chats/ and projects them onto the provider-agnostic toolpath-convo types and toolpath::v1::Path. Mirrors the toolpath-claude surface. Wires derive gemini and list gemini into toolpath-cli.

Design

Session layout. Main chat at chats/session-<timestamp>-<short>.json (kind: "main") plus optional sibling <full-uuid>/ dir holding kind: "subagent" chats. read_conversation loads the main file and folds sub-agent chats into DelegatedWork on the parent task invocation — turns is populated (richer than toolpath-claude, whose sub-agent turns stay empty).

Three-layer fidelity.

Layer Lossless? Use for
ChatFile / Conversation — raw on-disk schema yes (9 round-trip tests against 3 live fixtures) archival, redaction, re-emit byte-equivalent JSON
ConversationView — provider-agnostic projection no (Gemini-specifics under Turn.extra["gemini"]) cross-provider consumers
toolpath::v1::Path — provenance digest no (tool args/results summarized; file-write bodies kept in full) blame, query, rendering

Round-trip at the ChatFile layer is guaranteed by Option<Vec<T>> on optional list fields (absent vs [] preserved), GeminiRole::Other(String) catch-all for unknown roles, Option<serde_json::Value> on polymorphic resultDisplay, and #[serde(flatten)] extra at both chat and message levels for forward-compat.

RFC "at least one perspective." File-write ArtifactChange populates both raw (Gemini's resultDisplay.fileDiff, or a hand-rolled hunk) and structural (typed gemini.write_file / gemini.replace op with args).

Non-file-write tool args preserved. Shell commands, grep patterns, read targets, task prompts all land in structural.tool_calls[].summary of conversation.append steps — no data loss from derivation.

Field mapping

Source Derived location
sessionId gemini://<uuid> artifact URI + path.id short form
directories[0] path.base.uri (file://…)
User/Gemini message text change["gemini://…"].structural.text (verbatim)
info message step with actor: "system:gemini-cli"
model per-step actor (agent:gemini-3-flash-preview) + meta.actors
Tool name + status structural.tool_calls[].{name,status}
Shell command / file path / pattern / prompt structural.tool_calls[].summary
write_file / replace bodies file artifact raw (unified diff) + structural (typed op, args, byte count)
resultDisplay.fileDiff raw perspective on the file change
thoughts, tokens.*, tool results on ConversationView.Turn (not in the Path digest; --include-thinking opts into thoughts inline)

18 messages → 18 steps, 1:1. Every parent reference resolves; head valid.

Test plan

  • cargo test --workspace — all green (129 unit + 3 fixture + 9 round-trip + 4 doc tests in toolpath-gemini)
  • cargo clippy --workspace -- -D warnings — clean
  • path derive gemini … | path validate on real local session data
  • Three real fixtures round-trip byte-equivalent through ChatFile serde

Follow-ups

  • toolpath-claude has the same absent-vs-empty / null-dropping bug class; confirmed by running the round-trip check against real Claude JSONL (isSidechain injected, parentUuid: null dropped). Port the fix.
  • Push-based watcher for Gemini (notify + tokio) to match toolpath-claude's watcher parity.
  • Optional Path.meta.extra["gemini"]["chat_file"] side-channel for PathChatFile reversibility (the digest is one-way today).

@benbaarber benbaarber changed the title toolpath-gemin toolpath-gemini Apr 17, 2026
@benbaarber benbaarber requested a review from akesling April 17, 2026 19:48
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 17, 2026

🔍 Preview deployed: https://88ef161e.toolpath.pages.dev

Copy link
Copy Markdown
Contributor

@akesling akesling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Seems a reasonable enough first pass. I expect there's some low hanging fruit for some type reuse across providers and perhaps some better patterns to organize, but best to get this into the repo to help inform current work.

@benbaarber benbaarber merged commit 298fa07 into main Apr 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants